#include "preHeader.h"
#include "Session/GameSession.h"
#include "Session/GameSessionHandler.h"
#include "SQLHelper.h"

int GameSessionHandler::HandleLoadAllGuildInfo(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto LoadAllGuildInfo = [GSRPCAsyncTaskArgs]() {
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		size_t n = 0;
		uint32 lastInstID = 0;
		auto sqlFormat = CreateSQL4SelectEntity<GuildInformation>("Id>%u ORDER BY Id");
mark:	auto rst = connPtr->FastQueryFormat(sqlFormat.c_str(), lastInstID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<GuildInformation>(row);
			SaveToINetStream(instInfo, buffer);
			lastInstID = instInfo.Id;
			if (++n % 250 == 0) {
				GameSession::Feedback(gsPtr, buffer, info.sn, RPCErrorNone, false);
				buffer.Clear();
			}
		}
		if (connPtr->GetLastErrno() != 0) {
			goto mark;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(LoadAllGuildInfo));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleLoadAllGuildMember(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto LoadAllGuildMember = [GSRPCAsyncTaskArgs]() {
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		size_t n = 0;
		uint32 lastInstID = 0;
		auto sqlFormat = CreateSQL4SelectEntity<GuildMember>("playerId>%u ORDER BY playerId");
mark:	auto rst = connPtr->FastQueryFormat(sqlFormat.c_str(), lastInstID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<GuildMember>(row);
			SaveToINetStream(instInfo, buffer);
			lastInstID = instInfo.playerId;
			if (++n % 2500 == 0) {
				GameSession::Feedback(gsPtr, buffer, info.sn, RPCErrorNone, false);
				buffer.Clear();
			}
		}
		if (connPtr->GetLastErrno() != 0) {
			goto mark;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(LoadAllGuildMember));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleLoadAllGuildApply(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto LoadAllGuildApply = [GSRPCAsyncTaskArgs]() {
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		size_t n = 0;
		uint32 lastInstID[2]{};
		auto sqlFormat = CreateSQL4SelectEntity<GuildApply>(
			"playerId>%u OR (playerId=%u AND guildId>%u) ORDER BY playerId,guildId");
mark:	auto rst = connPtr->FastQueryFormat(
			sqlFormat.c_str(), lastInstID[0], lastInstID[0], lastInstID[1]);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<GuildApply>(row);
			SaveToINetStream(instInfo, buffer);
			lastInstID[0] = instInfo.playerId;
			lastInstID[1] = instInfo.guildId;
			if (++n % 2500 == 0) {
				GameSession::Feedback(gsPtr, buffer, info.sn, RPCErrorNone, false);
				buffer.Clear();
			}
		}
		if (connPtr->GetLastErrno() != 0) {
			goto mark;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(LoadAllGuildApply));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleNewOneGuildInstance(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto NewOneGuildInstance = [GSRPCAsyncTaskArgs]() {
		GuildInformation instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4InsertEntity(instInfo);
		auto rst = connPtr->Execute(sqlStr.c_str());
		if (!rst.second) {
			error = DBPErrorInsertMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(NewOneGuildInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleSaveOneGuildInstance(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto SaveOneGuildInstance = [GSRPCAsyncTaskArgs]() {
		static const std::vector<ssize_t> ingores =
			ConvertEntityFieldIndexs<GuildInformation>({"Id"});
		GuildInformation instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4UpdateEntity(instInfo, "Id=%u", ingores);
		auto rst = connPtr->ExecuteFormat(sqlStr.c_str(), instInfo.Id);
		if (!rst.second) {
			error = DBPErrorUpdateMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(SaveOneGuildInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleDeleteOneGuildInstance(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto DeleteOneGuildInstance = [GSRPCAsyncTaskArgs]() {
		auto Id = pckPtr->Read<uint32>();
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4DeleteEntity<GuildInformation>("Id=%u");
		auto rst = connPtr->ExecuteFormat(sqlStr.c_str(), Id);
		if (!rst.second) {
			error = DBPErrorDeleteMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(DeleteOneGuildInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleNewOneGuildMember(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto NewOneGuildMember = [GSRPCAsyncTaskArgs]() {
		GuildMember instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4InsertEntity(instInfo);
		auto rst = connPtr->Execute(sqlStr.c_str());
		if (!rst.second) {
			error = DBPErrorInsertMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(NewOneGuildMember));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleSaveOneGuildMember(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto SaveOneGuildMember = [GSRPCAsyncTaskArgs]() {
		static const std::vector<ssize_t> ingores =
			ConvertEntityFieldIndexs<GuildMember>({"playerId"});
		GuildMember instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4UpdateEntity(instInfo, "playerId=%u", ingores);
		auto rst = connPtr->ExecuteFormat(sqlStr.c_str(), instInfo.playerId);
		if (!rst.second) {
			error = DBPErrorUpdateMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(SaveOneGuildMember));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleDeleteOneGuildMember(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto DeleteOneGuildMember = [GSRPCAsyncTaskArgs]() {
		auto playerId = pckPtr->Read<uint32>();
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4DeleteEntity<GuildMember>("playerId=%u");
		auto rst = connPtr->ExecuteFormat(sqlStr.c_str(), playerId);
		if (!rst.second) {
			error = DBPErrorDeleteMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(DeleteOneGuildMember));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleNewOneGuildApply(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto NewOneGuildApply = [GSRPCAsyncTaskArgs]() {
		GuildApply instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4InsertEntity(instInfo);
		auto rst = connPtr->Execute(sqlStr.c_str());
		if (!rst.second) {
			error = DBPErrorInsertMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(NewOneGuildApply));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleDeleteGuildApply(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto DeleteGuildApply = [GSRPCAsyncTaskArgs]() {
		uint32 playerId, guildId;
		(*pckPtr) >> playerId >> guildId;
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		std::pair<my_ulonglong, bool> rst;
		if (playerId != 0 && guildId != 0) {
			rst = connPtr->ExecuteFormat(CreateSQL4DeleteEntity<GuildApply>
				("playerId=%u AND guildId=%u").c_str(), playerId, guildId);
		} else if (playerId != 0) {
			rst = connPtr->ExecuteFormat(CreateSQL4DeleteEntity<GuildApply>
				("playerId=%u").c_str(), playerId);
		} else {
			rst = connPtr->ExecuteFormat(CreateSQL4DeleteEntity<GuildApply>
				("guildId=%u").c_str(), guildId);
		}
		if (!rst.second) {
			error = DBPErrorDeleteMysqlFailed;
			return;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(DeleteGuildApply));
	return SessionHandleCapture;
}
